{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from flask import Flask, request, render_template, redirect,url_for,make_response,send_from_directory\n",
    "import os, fitz, zipfile, random\n",
    "from gevent import pywsgi\n",
    "from skimage.io import imread\n",
    "from skimage.transform import resize\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "app = Flask(__name__)\n",
    "UPLOAD_FLODER = './uploads'\n",
    "\n",
    "# 安全问题\n",
    "# 除了常规的CSRF防范，我们还需要重点关注这几个问题：验证文件类型、验证文件大小、过滤文件名\n",
    "black_list=['exe','sh','com','pif','bat','scr','sys','dll'] # 黑名单，不允许上传这些类型的文件\n",
    "def passport(filetype):\n",
    "    if filetype in black_list:\n",
    "        return 0 # 文件类型可疑\n",
    "    else:\n",
    "        return 1 # 文件类型安全\n",
    "\n",
    "app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 限制最大上传文件为100Mb\n",
    "\n",
    "def filter(file): # 过滤文件名\n",
    "    filename = file.filename.rsplit('.', 1)[0]\n",
    "    filetype = file.filename.rsplit('.', 1)[1]\n",
    "    if passport(filetype):\n",
    "        filename = filename.replace(' ','') # 将文件名中的空格去除\n",
    "        filename = filename.replace('.','-') # 去除文件中的.\n",
    "        filename = filename+'.'+filetype\n",
    "        return filename\n",
    "    else:\n",
    "        return 0 # 文件不安全\n",
    "\n",
    "def download(filename,directory = './'):# 假设在当前目录\n",
    "    # 需要知道2个参数, 第1个参数是本地目录的path, 第2个参数是文件名(带扩展名)\n",
    "    response = make_response(send_from_directory(directory, filename, as_attachment=True))\n",
    "    response.headers[\"Content-Disposition\"] = \"attachment; filename={}\".format(filename.encode().decode('latin-1'))\n",
    "    return response\n",
    "\n",
    "def pyMuPDF_fitz(pdfPath, imagePath, acc):# 将pdf转化为图片，放入相应的文件夹\n",
    "    print(\"imagePath=\"+imagePath)\n",
    "    pdfDoc = fitz.open(pdfPath)\n",
    "    for pg in range(pdfDoc.pageCount):\n",
    "        page = pdfDoc[pg]\n",
    "        rotate = int(0)\n",
    "        # 每个尺寸的缩放系数为1.3，这将为我们生成分辨率提高2.6的图像。\n",
    "        # 此处若是不做设置，默认图片大小为：792X612, dpi=96\n",
    "        zoom_x = 1.33333333*acc #(1.33333333-->1056x816)   (2-->1584x1224)\n",
    "        zoom_y = 1.33333333*acc\n",
    "        mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)\n",
    "        pix = page.getPixmap(matrix=mat, alpha=False)\n",
    "        \n",
    "        if not os.path.exists(imagePath):#判断存放图片的文件夹是否存在\n",
    "            os.makedirs(imagePath) # 若图片文件夹不存在就创建\n",
    "        \n",
    "        pix.writePNG(imagePath+'/'+'images_%s.png' % pg)#将图片写入指定的文件夹内\n",
    "    pdfDoc.close()\n",
    "    return 1\n",
    "\n",
    "def zip_ya(startdir, file_news): # 将文件压缩\n",
    "    z = zipfile.ZipFile(file_news,'w',zipfile.ZIP_DEFLATED) #参数一：文件夹名\n",
    "    for dirpath, dirnames, filenames in os.walk(startdir):\n",
    "        fpath = dirpath.replace(startdir,'') #这一句很重要，不replace的话，就从根目录开始复制\n",
    "        fpath = fpath and fpath + os.sep or ''#这句话理解我也点郁闷，实现当前文件夹以及包含的所有文件的压缩\n",
    "        for filename in filenames:\n",
    "            z.write(os.path.join(dirpath, filename),fpath+filename)\n",
    "        print ('%s压缩成功' % file_news)\n",
    "    z.close()\n",
    "\n",
    "def pic2pdf(path,name):\n",
    "    doc = fitz.open()\n",
    "    for img in os.listdir(path): # 读取图片，确保按文件名排序\n",
    "        # print(img)\n",
    "        imgdoc = fitz.open(os.path.join(path,img))         # 打开图片\n",
    "        pdfbytes = imgdoc.convertToPDF()    # 使用图片创建单页的 PDF\n",
    "        imgpdf = fitz.open(\"pdf\", pdfbytes)\n",
    "        doc.insertPDF(imgpdf)          # 将当前页插入文档\n",
    "    newpath = os.path.join(path, name)\n",
    "    if os.path.exists(\"%s.pdf\" % newpath):\n",
    "        os.remove(\"%s.pdf\" % newpath)\n",
    "    doc.save(\"%s.pdf\" % newpath)          # 保存pdf文件\n",
    "    doc.close()\n",
    "\n",
    "def combine_pdf_files(path,name):\n",
    "    doc = fitz.open()\n",
    "    for pdf in os.listdir(path): # 读取图片，确保按文件名排序\n",
    "        # print(img)\n",
    "        pdfbytes = fitz.open(os.path.join(path,pdf))         # 打开图片\n",
    "        doc.insertPDF(pdfbytes)          # 将当前页插入文档\n",
    "    newpath = os.path.join(path, name)\n",
    "    if os.path.exists(\"%s.pdf\" % newpath):\n",
    "        os.remove(\"%s.pdf\" % newpath)\n",
    "    doc.save(\"%s.pdf\" % newpath)          # 保存pdf文件\n",
    "    doc.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/', methods=['GET'])\n",
    "def index():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('index.html')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/Compress-picture', methods=['GET', 'POST'])\n",
    "def Compress_picture():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('Compress-picture.html')\n",
    "\n",
    "    elif request.method == 'POST':#post方法\n",
    "        file = request.files.get('file')\n",
    "        rate = float(request.form.get('rate'))\n",
    "        dpi = int(request.form.get('dpi'))\n",
    "        if dpi > 500:\n",
    "            return redirect(url_for(\"index\"))\n",
    "        \n",
    "        filename = os.path.join(UPLOAD_FLODER,file.filename)\n",
    "        file.save(filename)\n",
    "        \n",
    "        img = imread(filename)\n",
    "        # print(img.shape)\n",
    "        x = int(img.shape[0]*rate)\n",
    "        y = int(img.shape[1]*rate)\n",
    "        # print(x,y)\n",
    "        img = resize(img,(x,y))\n",
    "        print(img.shape)\n",
    "        plt.axis('off')\n",
    "        plt.imshow(img)\n",
    "        plt.savefig(filename,bbox_inches='tight',pad_inches=0.0,dpi=dpi)#,dpi=800\n",
    "        \n",
    "        # get file size\n",
    "        file.seek(0, os.SEEK_END)\n",
    "        size1 = file.tell()/1024/1024\n",
    "        size2 = os.stat('%s'%filename).st_size/1024\n",
    "        print(filename,'原大小%.2fMb, ' % size1,'压缩后大小为%.2fkb' % size2)\n",
    "        # print('分辨率比率为%s' % rate, '实际压缩比率为%.4f' % (size2/(1024*size1)))\n",
    "        \n",
    "        response = download(file.filename,UPLOAD_FLODER)\n",
    "        return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/pdf-to-pic', methods=['GET', 'POST'])\n",
    "def pdf_to_pic():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('pdf-to-pic.html')\n",
    "\n",
    "    elif request.method == 'POST':#post方法\n",
    "        file = request.files.get('file')\n",
    "        acc = int(request.form.get('acc'))\n",
    "        \n",
    "        filename = os.path.join(UPLOAD_FLODER,file.filename)\n",
    "        file.save(filename)\n",
    "        \n",
    "        name = file.filename.rsplit('.', 1)[0]\n",
    "        img_path = os.path.join(UPLOAD_FLODER, name)\n",
    "        pyMuPDF_fitz(filename, img_path, acc)\n",
    "        file_news = os.path.join(UPLOAD_FLODER, '%s.zip' % name) # 压缩后文件夹的名字\n",
    "        zip_ya(img_path, file_news)\n",
    "        \n",
    "        response = download('%s.zip' % name, UPLOAD_FLODER)\n",
    "        return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/pic-to-pdf', methods=['GET', 'POST'])\n",
    "def pic_to_pdf():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('pic-to-pdf.html')\n",
    "\n",
    "    elif request.method == 'POST':#post方法\n",
    "        temp_fold = os.path.join(UPLOAD_FLODER, str(random.randint(0,9999)))\n",
    "        if not os.path.exists(temp_fold):#判断存放图片的文件夹是否存在\n",
    "            os.makedirs(temp_fold) # 若图片文件夹不存在就创建\n",
    "        for file in request.files.getlist('file'):\n",
    "            filename = os.path.join(temp_fold, file.filename)\n",
    "            file.save(filename)\n",
    "        name = request.form.get('name')\n",
    "        \n",
    "        pic2pdf(temp_fold, name)\n",
    "        \n",
    "        response = download(name+\".pdf\", temp_fold)\n",
    "        return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@app.route('/combine-pdf', methods=['GET', 'POST'])\n",
    "def combine_pdf():\n",
    "    if request.method == 'GET':\n",
    "        return render_template('combine-pdf.html')\n",
    "\n",
    "    elif request.method == 'POST':#post方法\n",
    "        temp_fold = os.path.join(UPLOAD_FLODER, str(random.randint(0,9999)))\n",
    "        if not os.path.exists(temp_fold):#判断存放图片的文件夹是否存在\n",
    "            os.makedirs(temp_fold) # 若图片文件夹不存在就创建\n",
    "        for file in request.files.getlist('file'):\n",
    "            filename = os.path.join(temp_fold, file.filename)\n",
    "            file.save(filename)\n",
    "        name = request.form.get('name')\n",
    "        \n",
    "        combine_pdf_files(temp_fold, name)\n",
    "        \n",
    "        response = download(name+\".pdf\", temp_fold)\n",
    "        return response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "if __name__ == '__main__':\n",
    "    port=5000\n",
    "    server = pywsgi.WSGIServer(('0.0.0.0', port), app)\n",
    "    server.serve_forever()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
